/*
 * @(#)FileProcessorService.java  2.0 11/01/11
 * 
 */
package com.hidromedsa.measure.controller.filesprocessor;

import com.hidromedsa.measure.controller.templateprocessor.RulesHandler;
import com.hidromedsa.measure.controller.templateprocessor.RulesStructure;
import com.hidromedsa.measure.controller.util.FileContants;
import com.hidromedsa.measure.entities.AbstractRule;
import com.hidromedsa.measure.entities.FieldMedicion;
import com.hidromedsa.measure.entities.FieldTypesEnum;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBException;
import org.apache.commons.io.FileUtils;

/**
 * <p>Class that implements a service for the File Processor process</p>
 *
 * @version 2.0, 11/01/11
 * @since JDK1.0
 */
public class FileProcessorService {

    public static final String ENCODING = "UTF-8";
    /**
     * singleton instance for the service
     */
    private static FileProcessorService instance;
    private File fileRead;

    private FileProcessorService(File fileRead) {
        this.fileRead = fileRead;
    }

    public static synchronized FileProcessorService getInstance(File file) {

        instance = new FileProcessorService(file);

        return instance;
    }

    public File getFileRead() {
        return fileRead;
    }

    public void setFileRead(File fileRead) {
        this.fileRead = fileRead;
    }

    /**
     * <p> find all the field, and its values using a file </p>
     *
     * @param separator
     * @param headers
     * @param type
     * @return
     * @throws IOException
     */
    public ArrayList<FieldMedicion> findFieldsByFile(String separator, boolean headers, String type) throws IOException {

        ArrayList<FieldMedicion> fields = new ArrayList<FieldMedicion>();
        String encoding = ENCODING;
        List<String> listaLineas = FileUtils.readLines(fileRead, encoding);
        if (!listaLineas.isEmpty()) {
            String[] dataFirstLine = listaLineas.get(0).split(separator);
            int count = 0;
            for (String value : dataFirstLine) {
                FieldMedicion fieldMedicion = new FieldMedicion();
                if (headers) {
                    fieldMedicion.setName(value);
                    fieldMedicion.setValue(count);
                    fieldMedicion.setPosition(count);
                } else {
                    fieldMedicion.setName("Column" + count);
                    fieldMedicion.setValue(count);
                    fieldMedicion.setPosition(count);
                }
                fieldMedicion.setType(FieldTypesEnum.VARCHAR);
                count++;
                fields.add(fieldMedicion);
            }
        }

        System.out.println(fields.size());
        for (FieldMedicion fieldMedicion : fields) {
            fieldMedicion.setValues(getValuesColum(fieldMedicion.getPosition(), separator, headers));
        }

        return fields;
    }

    /**
     * <p>find all the fields and its rules</p>
     *
     * @param separator
     * @param headers
     * @param type
     * @return
     * @throws IOException
     */
    public RulesStructure findFieldsByFileWithTemplate(String separator, boolean headers, String type, String templateURL) throws IOException, JAXBException {


        File fileTemplate = new File(templateURL);
        ArrayList<FieldMedicion> fields = new ArrayList<FieldMedicion>();
        Map<String, ArrayList<String>> fieldsMap = new HashMap<String, ArrayList<String>>();
        String encoding = ENCODING;
        List<String> listaLineas = FileUtils.readLines(fileRead, encoding);
        if (!listaLineas.isEmpty()) {
            String[] dataFirstLine = listaLineas.get(0).split(separator);
            int count = 0;
            for (String value : dataFirstLine) {
                FieldMedicion fieldMedicion = new FieldMedicion();
                if (headers) {
                    fieldMedicion.setName(value);
                    fieldMedicion.setValue(count);
                    fieldMedicion.setPosition(count);
                } else {
                    fieldMedicion.setName("Column" + count);
                    fieldMedicion.setValue(count);
                    fieldMedicion.setPosition(count);
                }
                fieldMedicion.setType(FieldTypesEnum.VARCHAR);
                count++;
                fields.add(fieldMedicion);
            }
        }

        for (FieldMedicion fieldMedicion : fields) {
            fieldMedicion.setValues(getValuesColum(fieldMedicion.getPosition(), separator, headers));
            fieldsMap.put(fieldMedicion.getName(), new ArrayList(fieldMedicion.getValues()));
        }



        RulesStructure rules = RulesHandler.unmarshal(fileTemplate);

        for (AbstractRule rule : rules.getRules()) {

            try {
                if (fieldsMap.get(rule.getFieldIni().getName()) != null) {
                    rule.getFieldIni().setValues(fieldsMap.get(rule.getFieldIni().getName()));
                    // rule.getFieldEnd().setValues(fieldsMap.get(rule.getFieldEnd().getName()));0
                } else {

                    System.out.println(rule.getFieldIni().getName() + "values" + rule.getFieldIni().getValues());
                    rule.getFieldIni().setValues(rule.getResultField().getValues());
                    System.out.println(rule.getFieldIni().getName() + "values" + rule.getFieldIni().getValues());

                }


                if (rule.getFieldEnd() != null) {
                    rule.getFieldEnd().setValues(fieldsMap.get(rule.getFieldEnd().getName()));
                }




            } catch (Exception ex) {
            }
            rule.executeRules();
        }
        return rules;

    }

    /**
     * <p> Copy the fields and the rules used </p>
     *
     * @param rules
     * @param destinationURLResultFile
     * @param destinationURLTemplate
     * @param separator
     * @param header
     * @return
     * @throws IOException
     * @throws JAXBException
     */
    public boolean copyFilesUsingFields(ArrayList<AbstractRule> rules, String destinationURLResultFile, String destinationURLTemplate, String separator, String header, String endLine) throws IOException, JAXBException {

        RulesHandler.marshal(rules, new File(destinationURLTemplate), header, endLine, separator);
        ArrayList<FieldMedicion> fields = new ArrayList<FieldMedicion>();
        ArrayList<String> lines = new ArrayList<String>();
        for (AbstractRule rule : rules) {
            fields.add(rule.getResultField());
        }

        int numberElements = 0;
        if (fields.size() > 0) {
            numberElements = fields.get(0).getValues().size();
        }

        for (int i = 0; i < numberElements; i++) {
            String line = "";
            for (int j = 0; j < fields.size(); j++) {

                FieldMedicion field = fields.get(j);
                if (j > 0) {
                    line += separator;
                }
                line += field.getValues().get(i);
            }
            lines.add(line);
        }


        FileUtils.writeLines(new File(destinationURLResultFile), lines);

        return true;
    }

    /**
     * <p> Copy the fields and the rules used </p>
     *
     * @param rules
     * @param destinationURLResultFile
     * @param destinationURLTemplate
     * @param separator
     * @param header
     * @return
     * @throws IOException
     * @throws JAXBException
     */
    public boolean copyOnlyFileResultUsingFields(ArrayList<AbstractRule> rules, String destinationURLResultFile, String separator, String header, String endLine, boolean headers) throws IOException, JAXBException {


        ArrayList<FieldMedicion> fields = new ArrayList<FieldMedicion>();
        ArrayList<String> lines = new ArrayList<String>();

        String headerFields = "";
        for (AbstractRule rule : rules) {
            System.out.println("lineas finales 1   " + rule.getResultField().getValues().size());
            fields.add(rule.getResultField());
            headerFields += rule.getResultName() + separator;
        }

        if (headers) {
            if (!header.isEmpty()) {
                lines.add(header);
            } else {
                lines.add(headerFields);
            }
        }




        int numberElements = 0;
        if (fields.size() > 0) {
            numberElements = fields.get(0).getValues().size();
        }

        for (int i = 0; i < numberElements; i++) {
            String line = "";
            for (int j = 0; j < fields.size(); j++) {

                FieldMedicion field = fields.get(j);
                if (j > 0) {
                    line += separator;
                }
                try {
                    line += field.getValues().get(i);
                } catch (Exception ex) {
                }
            }
            if (!line.isEmpty()) {
                line += endLine;
                lines.add(line);
            }
        }

        System.out.println("lineas finales --->" + lines.size());
        FileUtils.writeLines(new File(destinationURLResultFile), lines);

        return true;
    }

    /**
     * <p> Copy the fields and the rules used </p>
     *
     * @param rules
     * @param destinationURLResultFile
     * @param destinationURLTemplate
     * @param separator
     * @param header
     * @return
     * @throws IOException
     * @throws JAXBException
     */
    public boolean copyFileOnlyTemplateUsingFields(ArrayList<AbstractRule> rules, String destinationURLTemplate, String header, String endLine, String separator) throws IOException, JAXBException {

        RulesHandler.marshal(rules, new File(destinationURLTemplate), header, endLine, separator);
        return true;
    }

    /**
     * <p> get the values for a column </p>
     *
     * @param colum
     * @param separator
     * @param headers
     * @return
     * @throws IOException
     */
    public List<String> getValuesColum(int colum, String separator, boolean headers) throws IOException {

        String encoding = ENCODING;
        List<String> listaLineas = FileUtils.readLines(fileRead, encoding);
        System.out.println(" ------------------ lines size   -----------------------" + listaLineas.size());
        List<String> returnData = new ArrayList<String>();

        for (int i = 0; i < listaLineas.size(); i++) {
            if (headers && i == 0) {
                continue;
            }
            String data = listaLineas.get(i);
            String[] dataFirstLine = data.split(separator);
            String textoSelected = "";
            if (dataFirstLine.length > colum) {
                textoSelected = dataFirstLine[colum];
            }
            returnData.add(textoSelected);

        }

        return returnData;
    }

    public List<File> listTemplates(String urlTemplate) {
        String extentions[] = {"xml"};
        System.out.println(urlTemplate);
        return new ArrayList(FileUtils.listFiles(new File(urlTemplate), extentions, true));
    }

    public void deleteTemplate(String path) {
        File fileDelete = new File(path);
        fileDelete.delete();
    }
}